//初始化ace编辑器对象
var editor = ace.edit("sql_content_editor");
ace.config.set('basePath', '/static/ace');
ace.config.set('modePath', '/static/ace');
ace.config.set('themePath', '/static/ace');

//设置风格和语言（更多风格和语言，请到github上相应目录查看）
var theme = "textmate";
var language = "text";
editor.setTheme("ace/theme/" + theme);
editor.session.setMode("ace/mode/" + language);
editor.$blockScrolling = Infinity;
editor.setValue("");

//字体大小
editor.setFontSize(12);

//设置只读（true时只读，用于展示代码）
editor.setReadOnly(false);

//自动换行,设置为off关闭
editor.setOption("wrap", "free");
editor.getSession().setUseWrapMode(true);

//启用提示菜单
ace.require("ace/ext/language_tools");
editor.setOptions({
    enableBasicAutocompletion: true,
    enableSnippets: true,
    enableLiveAutocompletion: true
});

//启用搜索扩展
ace.require("ace/ext/language_tools");

//绑定查询快捷键
editor.commands.addCommand({
    name: "alter",
    bindKey: { win: "Ctrl-Enter", mac: "Command-Enter" },
    exec: function (editor) {
        let pathname = window.location.pathname;
        if (pathname === "/sqlquery/") {
            dosqlquery()
        }
    }
});

let resourceMap = {}
let curTables = []

//是否表上下文
function checkTableContext(text) {
    var normalizedText = text.trim().toUpperCase();
    var tableKeywords = ['FROM', 'JOIN', 'INNER JOIN', 'LEFT JOIN', 'RIGHT JOIN', 'UPDATE'];

    for (let keyword of tableKeywords) {
        if (normalizedText.endsWith(keyword)) {
            return true;
        }
    }

    return false;
}

//是否字段上下文
function checkFieldContext(text) {
    var normalizedText = text.trim().toUpperCase();
    var columnKeywords = ['WHERE', 'AND', 'OR', 'GROUP BY', 'ORDER BY', 'SET'];

    for (let keyword of columnKeywords) {
        if (normalizedText.endsWith(keyword)) {
            return true;
        }
    }

    return false;
}

var getResourceMap = function () {
    $.ajax({
        type: "get",
        url: "/instance/instance_resource_info/",
        dataType: "json",
        async: true,
        data: {
            instance_name: $("#instance_name").val(),
        },
        success: function (data) {
            if (data.status === 0) {
                var result = data.data;
                resourceMap = result
            } else {
                alert(data.msg);
            }
        }
    });
}

//设置自动提示代码
var setCompleteData = function (data) {
    var langTools = ace.require("ace/ext/language_tools");
    langTools.addCompleter({
        getCompletions: function (editor, session, pos, prefix, callback) {
            if (prefix.length === 0) {
                return callback(null, []);
            } else {
                return callback(null, data);
            }
        }
    });
};

//增加数据库提示
function setDbsCompleteData(result) {
    var tables = [];
    for (var i = 0; i < result.length; i++) {
        tables.push({
            name: result[i],
            value: result[i],
            caption: result[i],
            meta: "database",
            score: 100
        });

    }
    setCompleteData(tables);
}

//增加模式提示
function setSchemasCompleteData(result) {
    var tables = [];
    for (var i = 0; i < result.length; i++) {
        tables.push({
            name: result[i],
            value: result[i],
            caption: result[i],
            meta: "schema",
            score: 100
        });

    }
    setCompleteData(tables);
}


//增加表提示
function setTablesCompleteData(result) {
    var meta = $("#db_name").val();
    if ($("#schema_name").val()) {
        meta = $("#schema_name").val();
    }
    var tables = [];
    for (var i = 0; i < result.length; i++) {
        tables.push({
            name: result[i],
            value: result[i],
            caption: result[i],
            meta: meta,
            score: 100
        });

    }
    setCompleteData(tables);
}

//增加字段提示
function setColumnsCompleteData(result) {
    if (result) {
        var tables = [];
        for (var i = 0; i < result.length; i++) {
            tables.push({
                name: result[i],
                value: result[i],
                caption: result[i],
                meta: $("#table_name").val(),
                score: 100
            });

        }
        setCompleteData(columns);
    } else {
        $.ajax({
            type: "get",
            url: "/instance/instance_resource/",
            dataType: "json",
            data: {
                instance_name: $("#instance_name").val(),
                db_name: $("#db_name").val(),
                schema_name: $("#schema_name").val(),
                tb_name: $("#table_name").val(),
                resource_type: "column"
            },
            complete: function () {
            },
            success: function (data) {
                if (data.status === 0) {
                    var result = data.data;
                    var columns = [];
                    for (var i = 0; i < result.length; i++) {
                        columns.push({
                            name: result[i],
                            value: result[i],
                            caption: result[i],
                            meta: $("#table_name").val(),
                            score: 100
                        })
                    }
                    setCompleteData(columns);
                } else {
                    alert(data.msg);
                }
            }
        });
    }
}

editor.on('change', (e) => {
    const session = editor.session;
    const cursorPos = editor.getCursorPosition();
    const line = session.getLine(cursorPos.row); //当前行的信息
    const charBeforeCursor = line.charAt(cursorPos.column); //最后一个字符

    const isTableContext = checkTableContext(line);
    const isFieldContext = checkFieldContext(line)

    const trigger_list = ['.', " ", ","];
    if (!trigger_list.includes(charBeforeCursor)) {
        return
    }

    if (!(isTableContext || isFieldContext) && charBeforeCursor === " ") {
        return
    }

    const db_name = $("#db_name").val();
    if (!db_name) {
        return
    }

    if (charBeforeCursor === ".") {
        //解析前面的信息
        const match = line.match(/\S+$/)
        if(!match){
            return
        }
        const curResource = match[0].slice(0, -1)
        //如果是数据库 提示下面的表
        if(Object.keys(resourceMap).includes(curResource)){
            const tables = Object.keys(resourceMap[curResource]) || []
            getSuggestions(tables, curResource)
            return
        }
        //如果是表 提示下面的字段
        const tables = Object.keys(resourceMap[db_name]) || []
        if(tables.includes(curResource)){
            const fields = resourceMap[db_name][curResource] || []
            getSuggestions(fields, curResource)
            return
        }
        //如果是表别名 提示下面的字段
        const tableList = curTables.filter(item => item.table == curResource || item.as == curResource)
        if(tableList.length > 0){
            getFiledSuggestions(tableList, false)
        }
        return
    }
    if (isTableContext) {
        //提示库名下面的表名
        if (!Object.keys(resourceMap).includes(db_name)) {
            return
        }
        const tables = Object.keys(resourceMap[db_name]) || []
        getSuggestions(tables, db_name)
        return
    }
    if (isFieldContext) {
        //提示表下面的字段
        if (Object.keys(resourceMap).includes(db_name)) {
            return
        }
        getFiledSuggestions(curTables, true)
    }

    if (isTableContext || isFieldContext || [".", ","].includes(charBeforeCursor)) {
        setTimeout(() => {
            editor.execCommand("startAutocomplete");
        }, 100);
    }
});

function getSuggestions(data, meta) {
    let completions = []
    for (let i = 0; i < data.length; i++) {
        completions.push({
            name: data[i],
            value: data[i],
            caption: data[i],
            score: 200,
            meta: meta
        })
    }
    return completions
}

function getFiledSuggestions(cTables, tipPrefix) {
    if (cTables.length === 0) {
        return []
    }
    const db_name = $("#db_name").val()
    const dbMap = resourceMap[db_name]
    let completions = []
    for (const curTable of cTables) {
        if(!Object.keys(dbMap).includes(curTable.table)){
            continue
        }
        const fields = dbMap[curTable.table]
        for (let i = 0; i < fields.length; i++) {
            completions.push({
                name: fields[i],
                value: tipPrefix && curTable.as ? `${curTable.as}.${fields[i]}` : fields[i],
                caption: fields[i],
                score: 200,
                meta: curTable.table
            })
        }
    }
    return completions
}

// 实例变更时修改language
$("#instance_name").change(function () {
    let optgroup = $('#instance_name :selected').parent().attr('label');
    if (optgroup === "MySQL") {
        editor.setTheme("ace/theme/" + "textmate");
        editor.session.setMode("ace/mode/" + "mysql");
        // 获取库表信息
        getResourceMap()
        // 提示信息
        let pathname = window.location.pathname;
        if (pathname === "/submitsql/" && !editor.getValue()) {
            editor.setValue("-- 请在此输入SQL，以分号结尾，仅支持DML和DDL语句，查询语句请使用SQL查询功能。\n");
            editor.clearSelection();
            editor.focus();  //获取焦点
        }
    } else if (optgroup === "MsSQL") {
        editor.setTheme("ace/theme/" + "sqlserver");
        editor.session.setMode("ace/mode/" + "sqlserver");
    } else if (optgroup === "Redis") {
        editor.setTheme("ace/theme/" + "textmate");
        editor.session.setMode("ace/mode/" + "text");
        editor.setOptions({
            enableSnippets: false,
        });
        // 提示信息
        let pathname = window.location.pathname;
        if (pathname === "/submitsql/" && !editor.getValue()) {
            editor.setValue("请在此输入命令，多个命令请换行填写，在提交时请删除此行说明");
            editor.focus();  //获取焦点
        }
    } else if (optgroup === "PgSQL") {
        editor.setTheme("ace/theme/" + "textmate");
        editor.session.setMode("ace/mode/" + "pgsql");
    } else if (optgroup === "Oracle") {
        editor.setTheme("ace/theme/" + "textmate");
        editor.session.setMode("ace/mode/" + "sql");
    } else if (optgroup === "Mongo") {
        editor.setTheme("ace/theme/" + "textmate");
        editor.session.setMode("ace/mode/" + "mongodb");
        editor.setOptions({
            enableSnippets: false,
        });
    } else {
        editor.setTheme("ace/theme/" + "textmate");
        editor.session.setMode("ace/mode/" + "mysql");
    }
});
